package com.opener.common.code.assistant.gen;

import com.opener.common.code.assistant.model.Prop;
import com.opener.common.code.assistant.model.Tab;
import org.springframework.util.StringUtils;

import java.util.ArrayList;
import java.util.List;

public class DaoMapperGenerator extends DaoGenerator{
    private static String TPL = "<?xml version=\"1.0\" encoding=\"UTF-8\" ?>\n" +
            "<!DOCTYPE mapper PUBLIC \"-//mybatis.org//DTD Mapper 3.0//EN\" \"http://mybatis.org/dtd/mybatis-3-mapper.dtd\" >\n" +
            "<mapper namespace=\"{namespace}\">\n" +
            "\n" +
            "\t<resultMap id=\"{resultMapId}\" type=\"{resultType}\">\n" +
            "\t{resultMap}\n"+
            "\t</resultMap>\n" +
            "\n" +
            "\t<insert id=\"add\" useGeneratedKeys=\"true\" keyProperty=\"id\" keyColumn=\"id\">\n" +
            "\t\t{insertSql}\n" +
            "\t</insert>\n" +
            "\n" +
            "\t<sql id=\"updateCond\">\n" +
            "\t\t<where>\n" +
            "\t\t\t<trim prefixOverrides=\"AND|OR\">\n" +
            "\t\t\t\tid=#{id}\n" +
            "\t\t\t</trim>\n" +
            "\t\t</where>\n" +
            "\t</sql>\n" +
            "\n" +
            "\t<update id=\"update\" >\n" +
            "\t\t{updateSql}\n" +
            "\t</update>\n" +
            "\n" +
            "\t<select id=\"get\" resultMap=\"{resultMapId}\">\n" +
            "\t\t{getSql}"+
            "\t</select>\n" +
            "\n" +
            "\t<sql id=\"searchCond\">\n" +
            "\t\t<where>\n" +
            "\t\t\t<trim prefixOverrides=\"AND|OR\">\n" +
            "\t\t\t\t{searchCondSql}\n" +
            "\t\t\t</trim>\n" +
            "\t\t</where>\n" +
            "\t</sql>\n" +
            "\t\n" +
            "\t<select id=\"search\" resultMap=\"{resultMapId}\">\n" +
            "\t\t{searchSql}\n" +
            "\t\t<if test=\"orderBy!=null and !orderBy.isEmpty()\">\n" +
            "\t\t\tORDER BY #{orderBy}\n" +
            "\t\t\t<if test=\"sort!=null and sort=='desc'\">desc </if>\n" +
            "\t\t</if>\n" +
            "\t\tLIMIT #{offset},#{pageSize}\n" +
            "\t</select>\n" +
            "\t<select id=\"getSearchCount\" resultType=\"java.lang.Integer\">\n" +
            "\t\t{searchCountSql}\n" +
            "\t</select>\n" +
            "</mapper>";

    public DaoMapperGenerator(Ctx ctx, Ctx.MvcClass mvcClass) {
        super(ctx, mvcClass);
    }

    public String createResultMap(){
        Tab tab = getMvcClass().getTab();
        List<Prop> props = tab.getProps();
        List results = new ArrayList();
        for (Prop p : props){
            String tag = "result";
            if (p.getDbField().equalsIgnoreCase("id")){
                tag = "id";
            }
            String extAttr = "";
            if ("set".equalsIgnoreCase(p.getDbType())){
                extAttr = " jdbcType=\"ARRAY\" javaType=\"java.util.List\" ";
            }
            results.add("<"+tag+" column=\""+p.getDbField()+"\" property=\""+p.getJavaProp()+"\""+extAttr+"/>");
        }
        String resultMapStr = "\t"+StringUtils.collectionToDelimitedString(results,"\n\t\t");
        return resultMapStr;

    }
    public String createInsertSql(){
        Tab tab = getMvcClass().getTab();
        List<Prop> props = tab.getProps();
        List dbFields = new ArrayList();
        List insertValues = new ArrayList();
        for (Prop p : props){
            if ("id".equalsIgnoreCase(p.getDbField()) || "update_uid".equalsIgnoreCase(p.getDbField()) || "update_time".equalsIgnoreCase(p.getDbField())){
                continue;
            }
            dbFields.add("`"+p.getDbField()+"`");
            String val = "#{"+p.getJavaProp()+"}";
            if ("create_time".equalsIgnoreCase(p.getDbField())){
                val = "NOW()";
            }
            insertValues.add(val);
        }
        String insertSql = "INSERT INTO `"+tab.getTable()+"`("+
                StringUtils.collectionToDelimitedString(dbFields,",")+
                ") \n"+
                "\t\tVALUES("+
                StringUtils.collectionToDelimitedString(insertValues,",")+
                ")";
        return insertSql;
    }
    public String createUpdateSql(){
        Tab tab = getMvcClass().getTab();
        List<Prop> props = tab.getProps();
        List updateFields = new ArrayList();
        for (Prop p : props){
            if ("id".equalsIgnoreCase(p.getDbField()) || "create_uid".equalsIgnoreCase(p.getDbField()) || "create_time".equalsIgnoreCase(p.getDbField())){
                continue;
            }
            updateFields.add("`"+p.getDbField()+"`=#{"+p.getJavaProp()+"}");
        }
        String updateSql = "UPDATE `"+tab.getTable()+"` SET\n\t\t"+
                StringUtils.collectionToDelimitedString(updateFields,",\n\t\t")+"\n"+
                "\t\t<include refid=\"updateCond\"/>";
        return updateSql;
    }
    public String createGetSql(){
        Tab tab = getMvcClass().getTab();
        List<Prop> props = tab.getProps();
        List dbFields = new ArrayList();
        List insertValues = new ArrayList();
        for (Prop p : props){
            dbFields.add("`"+p.getDbField()+"`");
        }
        String getSql = "SELECT "+
                StringUtils.collectionToDelimitedString(dbFields,",")+"\n"+
                "\t\tFROM `"+tab.getTable()+"`\n"+
                "\t\tWHERE id=#{id}\n";
        return getSql;
    }
    public String createSearchSql(){
        Tab tab = getMvcClass().getTab();
        List<Prop> props = tab.getProps();
        List dbFields = new ArrayList();
        List insertValues = new ArrayList();
        for (Prop p : props){
            dbFields.add("`"+p.getDbField()+"`");
        }
        String searchSql = "SELECT "+
                StringUtils.collectionToDelimitedString(dbFields,",")+"\n"+
                "\t\tFROM `"+tab.getTable()+"`\n"+
                "\t\t<include refid=\"searchCond\"/>\n";
        return searchSql;
    }

    public String createSearchCountSql(){
        Tab tab = getMvcClass().getTab();
        String searchCountSql = "SELECT count(1)\n"+
                "\t\tFROM `"+tab.getTable()+"`\n"+
                "\t\t<include refid=\"searchCond\"/>\n";
        return searchCountSql;
    }
    public String createSearchCondSql(){
        Tab tab = getMvcClass().getTab();
        String searchCountSql = "<if test=\"id!=null\">\n" +
                "\t\t\t\tid=#{id}\n" +
                "\t\t\t\t</if>";
        searchCountSql="";
        return searchCountSql;
    }
    @Override
    public String createJavaString(){
        Tab tab = getMvcClass().getTab();
        String xmlString = TPL;
        String insertSql = createInsertSql();
        String updateSql = createUpdateSql();
        String searchSql = createSearchSql();
        String searchCountSql = createSearchCountSql();
        String searchCondSql = createSearchCondSql();
        String getSql = createGetSql();
        String resultMap = createResultMap();
        Ctx.MvcClass modelCls = getCtx().getMvcClass("model");
        Ctx.MvcClass daoCls = getCtx().getMvcClass("dao");
        String resultMapId = Utils.lowerFistAlpha(modelCls.getClassName());
        String resultType = modelCls.getPkg()+"."+modelCls.getClassName();
        String namespace = daoCls.getPkg()+"."+daoCls.getClassName();
        xmlString = xmlString.replaceAll("\\{insertSql\\}", insertSql);
        xmlString = xmlString.replaceAll("\\{updateSql\\}", updateSql);
        xmlString = xmlString.replaceAll("\\{searchSql\\}", searchSql);
        xmlString = xmlString.replaceAll("\\{searchCountSql\\}", searchCountSql);
        xmlString = xmlString.replaceAll("\\{searchCondSql\\}", searchCondSql);
        xmlString = xmlString.replaceAll("\\{getSql\\}", getSql);
        xmlString = xmlString.replaceAll("\\{resultMapId\\}", resultMapId);
        xmlString = xmlString.replaceAll("\\{resultType\\}", resultType);
        xmlString = xmlString.replaceAll("\\{namespace\\}", namespace);
        xmlString = xmlString.replaceAll("\\{resultMap\\}", resultMap);

        return xmlString;
    }
}
